﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using Caliburn.Micro;
using CCWP7.Model;

namespace CCWP7.CaliburnMicro
{
    public class MainPageViewModel : Conductor<ProjectsViewModel>.Collection.AllActive
    {
        readonly IServerDataManager _serverDataManager;
        readonly INavigationService _navigationService;
        readonly Func<RefreshServer> _refreshServerFactory;
        readonly Func<ProjectsViewModel> _projectsVMFactory;
        readonly Func<ServersViewModel> _serversVMFactory;

        public MainPageViewModel(IServerDataManager serverDataManager,
        INavigationService navigationService,
        Func<ProjectsViewModel> projectsVMFactory,
        Func<RefreshServer> refreshServerFactory,
        Func<ServersViewModel> serversFactory)
        {
            Debug.Assert(serverDataManager != null, "serverDataManager is null.");
            Debug.Assert(navigationService != null, "navigationService is null.");
            Debug.Assert(projectsVMFactory != null, "projectsVMFactory is null.");
            Debug.Assert(refreshServerFactory != null, "refreshServerFactory is null.");
            Debug.Assert(serversFactory != null, "serversFactory is null.");

            _serverDataManager = serverDataManager;
            _navigationService = navigationService;
            _refreshServerFactory = refreshServerFactory;
            _projectsVMFactory = projectsVMFactory;
            _serversVMFactory = serversFactory;
        }

        ProjectsViewModel _projects;
        ProjectsViewModel _projectsFailed;
        ProjectsViewModel _projectsBuilding;

        public ProjectsViewModel AllProjects
        {
            get
            {
                return _projects;
            }
        }

        public ProjectsViewModel FailedProjects
        {
            get
            {
                return _projectsFailed;
            }
        }

        public ProjectsViewModel BuildingProjects
        {
            get
            {
                return _projectsBuilding;
            }
        }

        public ServersViewModel Servers { get; private set; }

        protected override void OnViewReady(object view)
        {
            base.OnViewReady(view);

            Debug.WriteLine("MainPageViewModel.OnViewReady");

            _projects = _projectsVMFactory();
            _projects.DisplayName = "all";
            Items.Add(_projects);

            _projectsFailed = _projectsVMFactory();
            _projectsFailed.DisplayName = "failed";
            _projectsFailed.Filter = p => p.LastBuildStatus == "Failure" || p.LastBuildStatus == "Exception";
            Items.Add(_projectsFailed);

            _projectsBuilding = _projectsVMFactory();
            _projectsBuilding.DisplayName = "building";
            _projectsBuilding.Filter = p => p.Activity != "Sleeping";
            Items.Add(_projectsBuilding);

            Servers = _serversVMFactory();

            CanRefreshModel = _serverDataManager.Servers.Where(s => s.Report != null)
            .SelectMany(s => s.Report.Projects)
            .Any();

            base.OnActivate();

            _projects.ActivateWith(this);

            NotifyOfPropertyChange(() => Items);

            _projects.Refresh();

            Refresh();
        }

        public void AddServer()
        {
            if (Microsoft.Phone.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
                _navigationService.Navigate(Constants.AddServerPage);
            else
                ReportNetworkNotAvailable();
        }

        bool _canRefreshModel;
        public bool CanRefreshModel
        {
            get
            {
                return _canRefreshModel;
            }
            set
            {
                _canRefreshModel = value;

                NotifyOfPropertyChange(() => CanRefreshModel);
            }
        }

        public IEnumerable<IResult> RefreshModel()
        {
            if (Microsoft.Phone.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
            {
                Debug.WriteLine("Refreshing Model...");

                CanRefreshModel = false;

                yield return new SetVisualState("Reading");

                foreach (var server in _serverDataManager.Servers)
                {
                    var rs = _refreshServerFactory();
                    rs.Server = server;

                    yield return rs;
                }

                yield return new SetVisualState("Default");

                foreach (var pvm in Items)
                    pvm.RefreshItems();

                CanRefreshModel = true;
            }
            else
                ReportNetworkNotAvailable();
        }

        static void ReportNetworkNotAvailable()
        {
            MessageBox.Show("Network not available, please try again later");
        }

        public void About()
        {
            _navigationService.Navigate(Constants.AboutPage);
        }
    }
}
